package config

import (
	"fmt"
	"io/fs"
	"log"
	"os"
	"strings"

	"code_gen/logger"
	"code_gen/utils"
	"gopkg.in/yaml.v3"
)

type Loader[T any] struct {
	config *T
	md5    string
}

func (cl *Loader[T]) refresh() {
	err := cl.load()
	if err != nil {
		fmt.Println("load config error", err)
	}
}
func (cl *Loader[T]) load() error {
	p, err := getConfigDir()
	if err != nil {
		return err
	}

	file := "config.yaml"
	devFile := "config-dev.yaml"
	_, err = os.Stat(fmt.Sprintf("%s%c%s", p, os.PathSeparator, devFile))
	if err == nil {
		file = devFile
	}
	configFilePath := fmt.Sprintf("%s%c%s", p, os.PathSeparator, file)

	logger.Log.Info("use config file: ", configFilePath)

	bytes, err := os.ReadFile(configFilePath)
	if err != nil {
		return err
	}

	md5 := utils.Md5(bytes)
	if md5 == cl.md5 {
		return nil
	}

	c := new(T)
	err = yaml.Unmarshal(bytes, c)
	if err != nil {
		return err
	}

	cl.md5 = md5
	cl.config = c

	return nil
}

func (cl *Loader[T]) Save() error {
	bts, err := yaml.Marshal(cl.config)
	if err != nil {
		return err
	}

	p, err := getConfigDir()
	if err != nil {
		return err
	}

	err = os.WriteFile(fmt.Sprintf("%s%c%s", p, os.PathSeparator, "config.yaml"), bts, fs.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

func (cl *Loader[T]) Get() *T {
	return cl.config
}

func (cl *Loader[T]) Init() *T {
	err := cl.load()
	if err != nil {
		log.Fatal(err)
	}

	return cl.config
}

func getConfigDir() (string, error) {
	for _, v := range os.Environ() {
		arr := strings.Split(v, "=")
		if arr[0] == "config_path" {
			return arr[1], nil
		}
	}

	return utils.GetExecPath()
}
